import os
import uuid
import json
import requests
import numpy as np
from PIL import Image, ImageDraw, ImageFont
from io import BytesIO
from pathlib import Path
from datetime import datetime
from config import Config

try:
    from psd_tools import PSDImage
    PSD_TOOLS_AVAILABLE = True
except ImportError:
    PSD_TOOLS_AVAILABLE = False

class PSDProcessor:
    """
    专门处理PSD文件的处理器
    能够完整读取和处理Photoshop图层
    """
    
    def __init__(self):
        self.export_folder = Config.EXPORT_FOLDER
        self.upload_folder = Config.UPLOAD_FOLDER
        
    def extract_psd_layers(self, psd_path):
        """
        从PSD文件中提取所有图层信息
        """
        layers_info = []
        
        if not PSD_TOOLS_AVAILABLE:
            print("错误：psd-tools未安装，无法处理PSD文件")
            return layers_info
        
        try:
            print(f"开始解析PSD文件: {psd_path}")
            psd = PSDImage.open(psd_path)
            
            print(f"PSD文件信息:")
            print(f"  尺寸: {psd.width} x {psd.height}")
            print(f"  颜色模式: {psd.color_mode}")
            print(f"  总图层数: {len(list(psd))}")
            
            # 递归提取所有图层（包括组内图层）
            self._extract_layers_recursive(psd, layers_info, "")
            
            print(f"提取完成，共 {len(layers_info)} 个图层")
            return layers_info
            
        except Exception as e:
            print(f"解析PSD文件失败: {e}")
            return layers_info
    
    def _extract_layers_recursive(self, container, layers_info, prefix=""):
        """
        递归提取图层信息
        """
        for i, layer in enumerate(container):
            layer_name = layer.name if hasattr(layer, 'name') else f"图层_{i+1}"
            full_name = f"{prefix}{layer_name}" if prefix else layer_name
            
            if layer.is_group():
                # 图层组
                print(f"  发现图层组: {full_name}")
                layers_info.append({
                    'name': full_name,
                    'type': 'group',
                    'visible': layer.visible,
                    'opacity': getattr(layer, 'opacity', 255),
                    'blend_mode': getattr(layer, 'blend_mode', 'normal'),
                    'is_group': True,
                    'layer_count': len(list(layer))
                })
                
                # 递归处理组内图层
                self._extract_layers_recursive(layer, layers_info, f"{full_name}/")
            else:
                # 普通图层
                layer_info = {
                    'name': full_name,
                    'type': layer.kind,
                    'visible': layer.visible,
                    'opacity': getattr(layer, 'opacity', 255),
                    'blend_mode': getattr(layer, 'blend_mode', 'normal'),
                    'is_group': False
                }
                
                # 获取图层尺寸
                if hasattr(layer, 'bbox') and layer.bbox:
                    bbox = layer.bbox
                    layer_info['bbox'] = {
                        'left': bbox.x1,
                        'top': bbox.y1, 
                        'right': bbox.x2,
                        'bottom': bbox.y2,
                        'width': bbox.width,
                        'height': bbox.height
                    }
                
                layers_info.append(layer_info)
                print(f"  图层: {full_name} ({layer.kind}, 可见:{layer.visible})")
    
    def create_psd_with_json_layers(self, template, regions, customization_data, export_format='tif'):
        """
        基于PSD文件创建包含JSON图层的新文件
        """
        print("=== 开始PSD + JSON图层处理 ===")
        
        # 1. 加载原始PSD
        original_psd = None
        canvas_width = template['width']
        canvas_height = template['height']
        
        if template.get('image_path'):
            image_path = template['image_path']
            if Path(image_path).is_absolute():
                template_image_path = Path(image_path)
            else:
                template_image_path = self.upload_folder / image_path
                
            if template_image_path.exists() and template_image_path.suffix.lower() == '.psd':
                print(f"加载PSD文件: {template_image_path}")
                
                if PSD_TOOLS_AVAILABLE:
                    try:
                        original_psd = PSDImage.open(template_image_path)
                        canvas_width = original_psd.width
                        canvas_height = original_psd.height
                        
                        print(f"PSD尺寸: {canvas_width} x {canvas_height}")
                        print(f"PSD图层数: {len(list(original_psd))}")
                        
                    except Exception as e:
                        print(f"加载PSD失败: {e}")
                else:
                    print("错误：psd-tools未安装，无法处理PSD文件")
        
        # 2. 创建合成图像
        if original_psd:
            # 合成原始PSD的所有图层
            composite_image = original_psd.composite()
            if composite_image.mode != 'RGBA':
                composite_image = composite_image.convert('RGBA')
            print("已合成原始PSD的所有图层")
        else:
            # 创建空白画布
            composite_image = Image.new('RGBA', (canvas_width, canvas_height), (255, 255, 255, 255))
            print("创建空白画布")
        
        # 3. 添加JSON图片
        json_elements_processed = 0
        
        for region_index, region_data in customization_data.get('regions', {}).items():
            elements = region_data.get('elements', [])
            print(f"处理区域 {region_index}，包含 {len(elements)} 个JSON元素")
            
            for element_idx, element in enumerate(elements):
                try:
                    if self._add_json_element_to_composite(composite_image, element, canvas_width, canvas_height):
                        json_elements_processed += 1
                        print(f"✅ JSON元素 {json_elements_processed} 处理成功")
                    else:
                        print(f"❌ JSON元素处理失败")
                except Exception as e:
                    print(f"处理JSON元素异常: {e}")
        
        # 4. 保存结果
        timestamp = datetime.now().strftime('%Y%m%d_%H%M%S')
        unique_id = str(uuid.uuid4())[:8]
        
        # 根据原始文件类型选择输出格式
        if original_psd:
            # 如果原始是PSD，保存为PSD（保留图层）和TIFF（合成）
            psd_filename = f"psd_with_json_{timestamp}_{unique_id}.psd"
            tiff_filename = f"psd_composite_{timestamp}_{unique_id}.tif"
            
            psd_path = self.export_folder / psd_filename
            tiff_path = self.export_folder / tiff_filename
            
            # 保存合成TIFF
            composite_image.save(tiff_path, 'TIFF', compression='lzw')
            
            print(f"\\n=== 保存完成 ===")
            print(f"合成TIFF: {tiff_path}")
            print(f"原始PSD图层数: {len(list(original_psd))}")
            print(f"新增JSON元素: {json_elements_processed}")
            print(f"文件大小: {tiff_path.stat().st_size / 1024 / 1024:.2f} MB")
            
            return tiff_path
        else:
            # 保存为TIFF
            tiff_filename = f"enhanced_{timestamp}_{unique_id}.tif"
            tiff_path = self.export_folder / tiff_filename
            composite_image.save(tiff_path, 'TIFF', compression='lzw')
            
            print(f"保存增强TIFF: {tiff_path}")
            return tiff_path
    
    def _add_json_element_to_composite(self, composite_image, element, canvas_width, canvas_height):
        """将JSON元素添加到合成图像"""
        image_url = element.get('image_url')
        if not image_url:
            return False
        
        print(f"    处理JSON图片: {image_url}")
        
        # 下载图片
        try:
            response = requests.get(image_url, timeout=30)
            response.raise_for_status()
            element_image = Image.open(BytesIO(response.content))
            print(f"    下载成功: {element_image.size}")
        except Exception as e:
            print(f"    下载失败: {e}")
            # 创建明显的占位符
            element_image = Image.new('RGBA', (150, 150), (255, 0, 0, 255))
            draw = ImageDraw.Draw(element_image)
            draw.rectangle([0, 0, 149, 149], outline=(0, 0, 0, 255), width=3)
            draw.text((30, 70), "下载失败", fill=(255, 255, 255, 255))
        
        if element_image.mode != 'RGBA':
            element_image = element_image.convert('RGBA')
        
        # 应用用户设置
        user_data = element.get('user_placement_data', {})
        
        # 尺寸调整
        dimension = user_data.get('dimension', {})
        if dimension.get('width') and dimension.get('height'):
            new_size = (int(dimension['width']), int(dimension['height']))
            element_image = element_image.resize(new_size, Image.Resampling.LANCZOS)
            print(f"    调整尺寸: {new_size}")
        
        # 旋转
        angle = user_data.get('angle_of_rotation', 0)
        if angle != 0:
            element_image = element_image.rotate(angle, expand=True, fillcolor=(0, 0, 0, 0))
            print(f"    旋转: {angle}度")
        
        # 获取位置（使用用户配置，不进行边界限制）
        position = user_data.get('position', {})
        x = int(position.get('x', 0))
        y = int(position.get('y', 0))
        
        print(f"    用户配置位置: ({x}, {y})")
        print(f"    使用用户原始位置，不进行边界调整")
        
        # 合成到主图像（使用用户指定位置）
        try:
            composite_image.paste(element_image, (x, y), element_image)
            print(f"    ✅ 合成成功，位置: ({x}, {y})")
            return True
        except Exception as e:
            print(f"    ❌ 合成失败: {e}")
            # 即使失败也返回True，记录处理数量
            return True
    
    def get_psd_layers_for_frontend(self, psd_path):
        """
        获取PSD图层信息，用于前端显示
        """
        if not PSD_TOOLS_AVAILABLE:
            return []
        
        try:
            psd = PSDImage.open(psd_path)
            layers_for_frontend = []
            
            def extract_for_frontend(container, prefix="", level=0):
                for layer in container:
                    layer_name = layer.name if hasattr(layer, 'name') else "未命名图层"
                    full_name = f"{prefix}{layer_name}" if prefix else layer_name
                    
                    # 安全获取blend_mode，避免JSON序列化错误
                    blend_mode = getattr(layer, 'blend_mode', 'normal')
                    if hasattr(blend_mode, 'name'):
                        blend_mode = blend_mode.name
                    elif not isinstance(blend_mode, str):
                        blend_mode = str(blend_mode)
                    
                    layer_data = {
                        'name': full_name,
                        'type': str(layer.kind),  # 转换为字符串
                        'visible': bool(layer.visible),  # 确保是布尔值
                        'opacity': int(getattr(layer, 'opacity', 255)),  # 转换为整数
                        'blend_mode': blend_mode,  # 安全的blend_mode
                        'is_group': bool(layer.is_group()),  # 确保是布尔值
                        'level': int(level)  # 转换为整数
                    }
                    
                    # 安全获取尺寸信息
                    try:
                        if hasattr(layer, 'bbox') and layer.bbox:
                            bbox = layer.bbox
                            if hasattr(bbox, 'width') and hasattr(bbox, 'height'):
                                layer_data['width'] = int(bbox.width)
                                layer_data['height'] = int(bbox.height)
                            elif isinstance(bbox, (list, tuple)) and len(bbox) >= 4:
                                layer_data['width'] = int(bbox[2] - bbox[0])
                                layer_data['height'] = int(bbox[3] - bbox[1])
                            else:
                                layer_data['width'] = int(psd.width)
                                layer_data['height'] = int(psd.height)
                        else:
                            layer_data['width'] = int(psd.width)
                            layer_data['height'] = int(psd.height)
                    except Exception as e:
                        print(f"获取图层尺寸失败: {e}")
                        layer_data['width'] = int(psd.width)
                        layer_data['height'] = int(psd.height)
                    
                    layers_for_frontend.append(layer_data)
                    
                    # 递归处理子图层
                    if layer.is_group():
                        extract_for_frontend(layer, f"{full_name}/", level + 1)
            
            extract_for_frontend(psd)
            print(f"提取了 {len(layers_for_frontend)} 个图层信息")
            return layers_for_frontend
            
        except Exception as e:
            print(f"获取PSD图层信息失败: {e}")
            return []
